﻿using Plugins.Common;
using Plugins.Historical;
using Plugins.UserControls;
using StockModel;
using System;
using System.Collections.Generic;
using System.Windows;

namespace Plugins.Base.Historical
{
    public class HistoricalDayProcessorBase : IDisposable
    {
        #region Properties

        public List<Operation> Operations { get; private set; }
        public List<FrameworkElement> CustomData { get; private set; }

        public DataFeeder DataFeeder { get; private set; }
		public OperationManager OperationManager { get; private set; }
		private FakeOrderExecutor FakeOrderExecutor { get; set; }

		protected DataLoader DataLoader { get; private set; }

        #endregion

        #region Public Methods

	    public HistoricalDayProcessorBase(QuotationDataSource quotationDataSource, RawStockDataSource rawStockDataSource, HourSelectorData hourOptions, StockParametersSelectorData stockParameters) : this(quotationDataSource, rawStockDataSource, hourOptions, stockParameters, false)
        {
        }

		public HistoricalDayProcessorBase(QuotationDataSource quotationDataSource, RawStockDataSource rawStockDataSource, HourSelectorData hourOptions, StockParametersSelectorData stockParameters, bool invertOperations)
		{
			this.FakeOrderExecutor = new FakeOrderExecutor();
			this.Operations = new List<Operation>();
			this.CustomData = new List<FrameworkElement>();

			this.OperationManager = new OperationManager(stockParameters, this.FakeOrderExecutor);
			this.OperationManager.Inverted = invertOperations;
			this.OperationManager.OperationExecuted += this.OperationManager_OperationExecuted; // Local Object

			this.DataLoader = new DataLoader(quotationDataSource, rawStockDataSource, this.FakeOrderExecutor);
			this.DataLoader.LastQuotation += this.DataLoader_LastQuotation; // Local Object

			this.DataFeeder = new DataFeeder(this.DataLoader.Data, hourOptions);
		}

        public void ProcessHistoricalItem(HistoricalItemToProcess item)
        {
            this.OperationManager.StockSymbol = item.Stock.Id.Code;
            this.DataLoader.Data.Clear();
            this.DataLoader.Load(item.Date, item.Stock);
			this.GenerateCustomData();
        }

		// Override this method if custom data has to be generated
		public virtual void GenerateCustomData()
		{
			
		}

        #endregion

        #region Event Handlers

        private void DataLoader_LastQuotation(object sender, EventArgs e)
        {
            this.DataFeeder.SetNextQuotationIsLastOne();
        }

        private void OperationManager_OperationExecuted(object sender, OperationExecutedEventArgs e)
        {
            this.Operations.Add(e.Operation);
        }

        #endregion

        #region IDisposable

        protected bool Disposed { get; private set; }

        private void Dispose(bool disposing)
        {
            if (!this.Disposed)
            {
                this.InternalDispose(disposing);
            }

            this.Disposed = true;
        }

        protected virtual void InternalDispose(bool disposing)
        {
            if (disposing)
            {
            	this.DataFeeder.Dispose();
			}

            // Dispose here only unmanaged objects 
            // Don’t use managed objects here because maybe 
            // they have been finalized already
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~HistoricalDayProcessorBase()
        {
            this.Dispose(false);
        }

        #endregion
    }
}
